package loja;

import helpers.Banco;
import helpers.Emailer;
import helpers.Endereco;
import helpers.Logger;
import interfaces.ClienteInterface;
import interfaces.ProdutoInterface;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.TreeMap;

import exceptions.ClienteErroLoginException;
import exceptions.ClienteJaExistenteException;
import exceptions.ClienteNaoEncontradoException;
import exceptions.CreditoInsuficienteException;

public class Cliente implements ClienteInterface, Serializable {

	private static final long serialVersionUID = 1L;

	private String nome;

	private int id;

	private String email;

	private String login;

	private String senha;

	private String telefone;

	private String cpf;

	private Double credito;

	private Endereco endereco;

	public String getNome() {
		return nome;
	}

	public int getId() {
		if (this.id != 0) {
			return this.id;
		}
		String sql = "Select id_cliente from Cliente where login = '"
				+ this.getLogin() + "'";
		ResultSet rs = Banco.retrieveQuery(sql);
		try {
			rs.first();
			int id = rs.getInt("id_cliente");
			this.id = id;
		} catch (SQLException e) {
			Logger.erro(e.toString());
		}
		return id;
	}

	public Double getCredito() {
		return credito;
	}

	public String getCpf() {
		return cpf;
	}

	private Cliente(String nome, String email, String login, String cpf,
			String telefone, String rua, String numero, String cep,
			Double credito) {
		this.telefone = telefone;
		this.nome = nome;
		this.email = email;
		this.login = login;
		this.cpf = cpf;
		this.endereco = new Endereco(rua, cep, numero);
		this.credito = credito;
		this.id = 0;
	}

	protected void adicionarCredito(double a) {
		this.credito += a;
	}

	protected void retirarCredito(double a) {
		this.credito -= a;
	}

	public void setSenha(String senha) {
		this.senha = senha;
		Cliente.updateCliente(this);
	}

	public void setNome(String nome) {
		this.nome = nome;
		Cliente.updateCliente(this);
	}

	public void setCredito(Double credito) {
		this.credito = credito;
		Cliente.updateCliente(this);
	}

	public String getEnderecoNumero() {
		return endereco.getNumero();
	}

	public String getEnderecoCep() {
		return endereco.getCep();
	}

	public String getEnderecoRua() {
		return endereco.getRua();
	}

	public String getEnderecoAdicional() {
		if (endereco.getAdicional() != null)
			return this.endereco.getAdicional();
		String sql = "select * from Cliente where login='" + login + "'";
		ResultSet rs = Banco.retrieveQuery(sql);
		try {
			rs.first();
			this.endereco.setAdicional(rs.getString("end_add"));
			return this.endereco.getAdicional();
		} catch (SQLException e) {
			Logger.erro(e.toString());
		}
		return null;
	}

	public void setEnderecoNumero(String numero) {
		this.endereco.setNumero(numero);
		Cliente.updateCliente(this);
	}

	public void setEnderecoCep(String cep) {
		this.endereco.setCep(cep);
		Cliente.updateCliente(this);
	}

	public void setEnderecoRua(String rua) {
		this.endereco.setRua(rua);
		Cliente.updateCliente(this);
	}

	public void setEnderecoAdicional(String adicional) {
		this.endereco.setAdicional(adicional);
		Cliente.updateCliente(this);
	}

	public String getEmail() {
		return email;
	}

	protected void setEmail(String email) {
		this.email = email;
		Cliente.updateCliente(this);
	}

	public String getLogin() {
		return login;
	}

	public String getTelefone() {
		return telefone;
	}

	public void setTelefone(String telefone) {
		this.telefone = telefone;
		Cliente.updateCliente(this);
	}

	public static Cliente getClienteByLogin(String Login, String senha)
			throws ClienteNaoEncontradoException, ClienteErroLoginException {

		String sql = "select * from cliente where login = '" + Login + "'";
		ResultSet rs = Banco.retrieveQuery(sql);

		Cliente c = null;

		try {

			if (!rs.first()) {
				throw new ClienteNaoEncontradoException();
			}

			String passwd = rs.getString("passwd");
			if (!senha.equals(passwd)) {
				throw new ClienteErroLoginException();
			}

			String nome = rs.getString("nome");
			String cpf = rs.getString("cpf");
			Double credito = rs.getDouble("credito");
			String rua = rs.getString("end_rua");
			String cep = rs.getString("end_cep");
			String num = rs.getString("end_num");
			String telefone = rs.getString("telefone");
			String login = rs.getString("login");
			String email = rs.getString("email");
			String adicional = rs.getString("end_add");

			c = new Cliente(nome, email, login, cpf, telefone, rua, num, cep,
					credito);
			c.setEnderecoAdicional(adicional);
		} catch (SQLException e) {

			Logger.erro(e.toString());
		}
		return c;

	}

	public static Cliente getClienteByLogin(String Login)
			throws ClienteNaoEncontradoException, ClienteErroLoginException {

		String sql = "select * from cliente where login = '" + Login + "'";
		ResultSet rs = Banco.retrieveQuery(sql);

		Cliente c = null;

		try {

			if (!rs.first()) {
				throw new ClienteNaoEncontradoException();
			}

			String nome = rs.getString("nome");
			String cpf = rs.getString("cpf");
			Double credito = rs.getDouble("credito");
			String rua = rs.getString("end_rua");
			String cep = rs.getString("end_cep");
			String num = rs.getString("end_num");
			String telefone = rs.getString("telefone");
			String login = rs.getString("login");
			String email = rs.getString("email");

			c = new Cliente(nome, email, login, cpf, telefone, rua, num, cep,
					credito);
			// c.setEnderecoAdicional(adicional);
		} catch (SQLException e) {

			Logger.erro(e.toString());
		}
		return c;
	}

	public static Cliente adicionarCliente(String nome, String email,
			String login, String passwd, String cpf, String telefone,
			String rua, String numero, String cep, Double credito)
			throws ClienteJaExistenteException {

		// Verifica login
		String sql = "select count(id_cliente) from cliente where login = '"
				+ login + "'";
		int quantidade = Banco.getQuantidade(sql);

		if (quantidade >= 1)
			throw new ClienteJaExistenteException();

		// Verifica Email
		sql = "select count(id_cliente) from cliente where email = '" + email
				+ "'";
		quantidade = Banco.getQuantidade(sql);

		if (quantidade >= 1)
			throw new ClienteJaExistenteException();

		// Verifica cpf
		sql = "select count(id_cliente) from cliente where cpf = '" + cpf + "'";
		quantidade = Banco.getQuantidade(sql);

		if (quantidade >= 1)
			throw new ClienteJaExistenteException();

		Cliente c;

		c = new Cliente(nome, email, login, cpf, telefone, rua, numero, cep,
				credito);
		sql = "Insert into Cliente "
				+ "(nome, cpf, credito, end_rua, end_cep, end_num, login, passwd, email, telefone ) "
				+ "values (?,?,?,?,?,?,?,?,?,?)";
		try {
			PreparedStatement ps = Banco.prepareStatement(sql);
			ps.setString(1, nome);
			ps.setString(2, cpf);
			ps.setDouble(3, credito);
			ps.setString(4, rua);
			ps.setString(5, cep);
			ps.setString(6, numero);
			ps.setString(7, login);
			ps.setString(8, passwd);
			ps.setString(9, email);
			ps.setString(10, telefone);
			Banco.executePreparedStatement(ps);
		} catch (SQLException e) {
			Logger.erro(e.toString());
		}
		c.setTelefone(telefone);
		Logger.adicionaCliente(c.login);
		
		return c;
	}

	public static ClienteInterface updateCliente(String nome, String login,
			String senha, String telefone, String rua, String numero,
			String adicional, String cep, ClienteInterface cliente)
			throws SQLException {

		Cliente c = (Cliente) cliente;

		c.setNome(nome);
		c.setSenha(senha);
		c.setTelefone(telefone);
		c.setEnderecoRua(rua);
		c.setEnderecoNumero(numero);
		c.setEnderecoAdicional(adicional);
		c.setEnderecoCep(cep);

		return c;
	}

	public static void updateCliente(Cliente a) {
		int id = a.getId();
		String nome = a.getNome();
		String email = a.getEmail();
		String senha = a.getSenha();
		String telefone = a.getTelefone();
		String cpf = a.getCpf();
		String rua = a.endereco.getRua();
		String numero = a.endereco.getNumero();
		String adicional = a.endereco.getAdicional();
		String cep = a.endereco.getCep();
		double credito = a.getCredito();

		String sql = "UPDATE Cliente SET nome = ?," + " credito= ?,"
				+ " email= ?," + " passwd= ?," + " telefone= ?,"
				+ " end_add= ?," + " cpf=?," + " end_rua=?," + " end_num=?,"
				+ " end_cep=?" + " WHERE id_cliente=?";
		PreparedStatement update;
		try {
			update = Banco.prepareStatement(sql);
			update.setString(1, nome);
			update.setDouble(2, credito);
			update.setString(3, email);
			update.setString(4, senha);
			update.setString(5, telefone);
			update.setString(6, adicional);
			update.setString(7, cpf);
			update.setString(8, rua);
			update.setString(9, numero);
			update.setString(10, cep);
			update.setInt(11, id);
			update.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			Logger.erro(e.toString());
		}
	}

	public String getSenha() {
		if (this.senha != null) {
			return this.senha;
		}
		String sql = "select * from Cliente where login='" + login + "'";
		ResultSet rs = Banco.retrieveQuery(sql);
		try {
			rs.first();
			this.senha = rs.getString("passwd");
			return this.senha;
		} catch (SQLException e) {
			Logger.erro(e.toString());
		}
		return null;
	}

	public static void esqueceuSenha(String login)
			throws ClienteNaoEncontradoException {
		String passwd, email, texto;
		String sql = "select * from Cliente where login='" + login + "'";
		ResultSet rs = Banco.retrieveQuery(sql);
		try {
			rs.first();
			passwd = rs.getString("passwd");
			email = rs.getString("email");
			texto = "A sua Senha e : " + passwd + ".";
			String arrayEmail[] = { email };
			String arrayCc[] = {};
			Emailer.sendMail(arrayEmail, arrayCc, arrayCc,
					"Recuperacao de Senha", texto);
		} catch (SQLException e) {
			throw new ClienteNaoEncontradoException();
		}
	}

	public static void cadastrouCliente(Cliente cliente) {

		String arrayEmail[] = { cliente.getEmail() };
		String arrayCc[] = {};
		String texto = "Parabéns por ter se registrado em nossa loja!\n\nSeus dados são:"
				+ "\n\n     -Nome do cliente: "
				+ cliente.getNome()
				+ "\n     -Login: "
				+ cliente.getLogin()
				+ "\n     -Senha: "
				+ cliente.getSenha()
				+ "\n     -Telefone: "
				+ cliente.getTelefone()
				+ "\n     -Cpf: "
				+ cliente.getCpf()
				+ "\n     -Credito na Loja: "
				+ cliente.getCredito()
				+ "\n     -Endereco: "
				+ cliente.getEnderecoRua()
				+ ", numero "
				+ cliente.getEnderecoNumero();
		if (cliente.getEnderecoAdicional() != null) {
			texto += ", "
					+ cliente.getEnderecoAdicional()
					+ ". CEP: "
					+ cliente.getEnderecoCep()
					+ ". \n\nCaso tenha algum campo incorreto, favor editar perfil em nossa loja!\n"
					+ "\n\nA Loja GPs agradece a preferencia.";
		} else {
			texto += ". CEP: "
					+ cliente.getEnderecoCep()
					+ ". \n\nCaso tenha algum campo incorreto, favor editar perfil em nossa loja!\n"
					+ "\n\nA Loja GPs agradece a preferencia.";
		}

		Emailer.sendMail(arrayEmail, arrayCc, arrayCc, "Cadastro de Cliente",
				texto);
	}

	public static void efetuaCompra(ClienteInterface clienteInterface,
			TreeMap<ProdutoInterface, Integer> treeMap, double total)
			throws CreditoInsuficienteException {
		Cliente a = (Cliente) clienteInterface;
		if (a.getCredito() < total) {
			throw new CreditoInsuficienteException();
		} else {
			Iterator<ProdutoInterface> itr = treeMap.keySet().iterator();
			while (itr.hasNext()) {
				Produto p = (Produto) itr.next();
				p.setQuantidadeCarrinho(p.getQuantidadeCarrinho()
						- treeMap.get(p));
				p.setQuantidadeEstoque(p.getQuantidadeEstoque()
						- treeMap.get(p));
			}
			a.setCredito(a.getCredito() - total);
			enviaEmailEfetuouCompra(a, treeMap, total);
			Logger.executaVenda(a.getLogin(), treeMap, total);
		}
	}

	public static boolean enviaEmailEfetuouCompra(Cliente a,
			TreeMap<ProdutoInterface, Integer> tree, Double total) {

		String[] to = { a.getEmail() };
		String subject = "Compra Efetuada Com sucesso";
		Iterator<ProdutoInterface> itr = tree.keySet().iterator();
		String text;
		int i = 0;
		text = "Sua Compra foi concluída , você comprou:\n";
		i++;
		while (itr.hasNext()) {
			Produto p = (Produto) itr.next();
			text += " " + p.getNome() + " " + tree.get(p).toString() + "x \n";
		}
		String[] cc = {};
		String[] bcc = {};
		Emailer.sendMail(to, cc, bcc, subject, text);
		return false;
	}

}